import re

##将正则表达式编译为pattern对象
regx_newLine = re.compile("\n")
regx_timescale = re.compile("`timescale +([0-9]+)([a-zA-Z]+)/([0-9]+)([a-zA-Z]+)")
regx_comment = re.compile("(//.*)")
regx_define = re.compile("`define +(\w+).+'([bh])([0-9a-f]+)")
regx_parameter = re.compile("parameter ?(\w+) ?= ?'([b|h])(\d+)")
regx_module = re.compile(" *module +(\w+).+;")
regx_endmodule = re.compile("endmodule")
regx_input = re.compile("input +([\w, ]+);")
regx_input_width = re.compile("input +\[([0-9]+):([0-9]+)\] +([\w ,]+);")
regx_output = re.compile("output +([\w, ]+);")
regx_output_width = re.compile("output +\[([0-9]+):([0-9]+)\] +([\w ,]+);")
regx_reg_var = re.compile("(?:reg|wire) +\[([0-9]+):([0-9]+)\](.+);")
regx_assign = re.compile("assign +(?P<lvar>\w+) +=(?P<rvar>.+);")
regx_always = re.compile(" *always@.*")
regx_always_replace = re.compile(" *(always.*(\n.*)*)")

#always块使用的正则
regx_value=re.compile("( *)(?P<lvar>\w+) +=(?P<rvar>.+);")
regx_value1=re.compile("( *)(?P<lvar>.+)=(?P<rvar>.+);")
regx_ifsen=re.compile(".*if *\((.*)\)")
regx_if=re.compile(" *(\w+) *==.*?")
regx_if1=re.compile("(\W?)(\w+)")
regx_case1=re.compile("( *)case *\( *(\w+) *\)")

# verilog_file = "CompressExtend.v"
verilog_file = "SM3_controller.v"
f_vlog = open(verilog_file, 'r')
f_cpp  = open(verilog_file[:-2]+".cpp", 'w')
f_hpp  = open(verilog_file[:-2]+".hpp", 'w')

f_hpp.write("#pragma onece\n")
f_hpp.write("#include \"systemc.h\"\n");
f_cpp.write("#include "+'\"'+verilog_file[:-2]+".hpp"+'\"'+'\n') # #include "CompressExtend.h"

module_name = "my_module" # default name of module
ctor_text=""
always_text=[]
always_sensitive_text=[]
always_nums=0

##replace函数的作用是对assign等号右边的变量进行匹配 然后替换为想要的内容
def replace(matched_obj):
    matched = matched_obj.group('var')
    regx_var = re.compile("\w+$")  # variables
    regx_varRange = re.compile("(\w+)\[(\d+):(\d+)\]")
    regx_varBitSel = re.compile("(\w+)\[(\d+)\]")
    regx_value = re.compile("\d*'([bdhoBHDO])([\da-f]+)")
    regx_bracket = re.compile("(\{|\})")
    res_str = "None"
    if regx_var.match(matched):
        res_str = "%s.read()" %matched
    elif regx_varRange.match(matched):
        match_obj = regx_varRange.match(matched)
        # print(match_obj.group(1)+ " " +match_obj.group(2)+ " " +match_obj.group(3))
        res_str = "%s.read().range(%s, %s)" %(match_obj.group(1), match_obj.group(2), match_obj.group(3))
    elif regx_varBitSel.match(matched):
        match_obj = regx_varBitSel.match(matched)
        res_str = "%s.read()[%s]" %(match_obj.group(1), match_obj.group(2))
    elif regx_value.match(matched):
        match_obj = regx_value.match(matched)
        type, value = match_obj.group(1), match_obj.group(2)
        if type == 'b':
            res_str = "0b%s" %value
        elif type == 'd':
            res_str = "%s" %value
        else:
            res_str = "0x%s" %value
    elif regx_bracket.match(matched):
        match_obj = regx_bracket.match(matched)
        if match_obj.group(1) == '{':
            res_str = '('
        else:
            res_str = ')'
    else:
        pass
    return res_str

##replace1的作用是吧assign右边的信号提取出来，输出为敏感表
def replace1(matched_obj1):
    matched1 = matched_obj1.group('var')
    regx_var = re.compile("\w+$")  # variables
    regx_varRange = re.compile("(\w+)\[(\d+):(\d+)\]")
    regx_varBitSel = re.compile("(\w+)\[(\d+)\]")
    regx_value = re.compile("\d*'([bdh])([\da-f]+)")
    regx_bracket = re.compile("(\{|\})")
    regx_symbol = re.compile("(\^|\,|\+|&|\||\(|\)|\?|<|~|:)")
    # res_str = "None"
    sen_value="None"
    if regx_var.match(matched1):
        # res_str = "%s.read()" %matched
        sen_value = " < < %s"%matched1
    elif regx_varRange.match(matched1):
        match_obj1 = regx_varRange.match(matched1)
        # print(match_obj.group(1)+ " " +match_obj.group(2)+ " " +match_obj.group(3))
        # res_str = "%s.read().range(%s, %s)" %(match_obj1.group(1), match_obj1.group(2), match_obj1.group(3))
        sen_value = "< < %s"%match_obj1.group(1)
    elif regx_varBitSel.match(matched1):
        match_obj1 = regx_varBitSel.match(matched1)
        # res_str = "%s.read()[%s]" %(match_obj1.group(1), match_obj1.group(2))
        sen_value = "< < %s" % match_obj1.group(1)
    elif regx_value.match(matched1):
        match_obj1 = regx_value.match(matched1)
        sen_value = ""
        # type, value = match_obj1.group(1), match_obj1.group(2)
        # if type == 'b':
        #     res_str = "0b%s" %value
        # elif type == 'd':
        #     res_str = "%s" %value
        # else:
        #     res_str = "0x%s" %value
    elif regx_bracket.match(matched1):
        match_obj1 = regx_bracket.match(matched1)
        sen_value = ""
        # if match_obj1.group(1) == '{':
        #     res_str = '('
        # else:
        #     res_str = ')'
    elif regx_symbol.match(matched1):
        match_obj1 = regx_symbol.match(matched1)
        if match_obj1.group(1) == '\+':
            sen_value = ""
        # elif match_obj1.group(1) == ',':
        #     sen_value = ""
        else:
            sen_value = ""
    else:
        pass
    return sen_value


##replace2的作用是提取always块里面等式的右边信号
def replace2(matched_obj2):
    matched2 = matched_obj2.group('var')
    regx_var = re.compile("\w+$")  # variables
    regx_varRange = re.compile(" *(\w+)\[(\d+):(\d+)\]")
    regx_varBitSel = re.compile("(\w+)\[(\d+)\]")
    regx_value = re.compile("\d*'([bdhoBHDO])([\da-f]+)")
    res_str = "None"
    if regx_var.match(matched2):
        if matched2 not in define_value:
            res_str = "%s.read()" %matched2
        else:
            res_str = "%s" % matched2
    elif regx_varRange.match(matched2):
        match_obj2 = regx_varRange.match(matched2)
        # print(match_obj.group(1)+ " " +match_obj.group(2)+ " " +match_obj.group(3))
        res_str = "%s.range(%s, %s)" %(match_obj2.group(1), match_obj2.group(2), match_obj2.group(3))
    elif regx_varBitSel.match(matched2):
        match_obj2 = regx_varBitSel.match(matched2)
        res_str = "%s.read()[%s]" %(match_obj2.group(1), match_obj2.group(2))
    elif regx_value.match(matched2):
        match_obj2 = regx_value.match(matched2)
        type, value = match_obj2.group(1), match_obj2.group(2)
        if type == 'b':
            res_str = "%s" %value
        elif type == 'd':
            res_str = "%s" %value
        else:
            res_str = "0x%s" %value

    else:
        pass
    return res_str

##replace3的作用是提取always块里面等式的左边信号
def replace3(matched_obj3):
    matched3 = matched_obj3.group('var')
    regx_var = re.compile("\w+$")  # variables
    regx_varRange = re.compile(" *(\w+)\[(\d+):(\d+)\]")
    regx_varBitSel = re.compile("(\w+)\[(\d+)\]")
    regx_value = re.compile("\d*'([bdhoBHDO])([\da-f]+)")
    res_str = "None"
    if regx_var.match(matched3):
        res_str = "%s" %matched3
    if regx_varRange.match(matched3):
        match_obj3 = regx_varRange.match(matched3)
        # print(match_obj.group(1)+ " " +match_obj.group(2)+ " " +match_obj.group(3))
        res_str = "%s.range(%s, %s)" %(match_obj3.group(1), match_obj3.group(2), match_obj3.group(3))
    else:
        pass
    return res_str


many_newline=0
define_value=[]
always_block_array=[]
##按行读取文本并且转换
for line in f_vlog.readlines():
    if regx_newLine.match(line) and many_newline==0:
        f_hpp.write("\n")
        many_newline=1
    else:
        if regx_timescale.match(line):
            match_obj = regx_timescale.match(line)
            f_hpp.write("#define CYCLK %s\n" %match_obj.group(1))
            many_newline=0
        elif regx_comment.match(line):
            f_hpp.write(regx_comment.match(line).group(1)+"\n")
            many_newline = 0
        elif regx_define.match(line):
            match_obj = regx_define.match(line)
            define_value.append(match_obj.group(1))
            if match_obj.group(2) == 'h':
                f_hpp.write("#define %s 0x%s\n" %(match_obj.group(1),match_obj.group(3)))
                many_newline = 0
            else:
                f_hpp.write("#define %s 0b%s\n" %(match_obj.group(1),match_obj.group(3)))
                many_newline = 0
        elif regx_parameter.match(line):
            match_obj = regx_parameter.match(line)
            if match_obj.group(2) == 'h':
                f_hpp.write("#define %s 0x%s\n" %(match_obj.group(1),match_obj.group(3)))
                many_newline = 0
            else:
                f_hpp.write("#define %s 0b%s\n" %(match_obj.group(1),match_obj.group(3)))
                many_newline = 0
        elif regx_module.match(line):
            match_obj = regx_module.match(line)
            module_name = match_obj.group(1)
            f_hpp.write("SC_MODULE(%s)\n{\n" %match_obj.group(1))
            many_newline = 0
        elif regx_input.match(line):
            f_hpp.write("\tsc_in<bool> %s;\n" %regx_input.match(line).group(1))
            many_newline = 0
        elif regx_input_width.match(line):
            match_obj = regx_input_width.match(line)
            data_width = int(match_obj.group(1))-int(match_obj.group(2))+1
            if data_width<=64:
                f_hpp.write("\tsc_in<sc_int<%d> > %s;\n" %(data_width, match_obj.group(3)))
                many_newline = 0
            else:
                f_hpp.write("\tsc_in<sc_bigint<%d> > %s;\n" %(data_width, match_obj.group(3)))
                many_newline = 0
        elif regx_output.match(line):
            f_hpp.write("\tsc_out<bool> %s;\n" %regx_output.match(line).group(1))
            many_newline = 0
        elif regx_output_width.match(line):
            match_obj = regx_output_width.match(line)
            data_width = int(match_obj.group(1))-int(match_obj.group(2))+1
            if data_width<=64:
                f_hpp.write("\tsc_out<sc_int<%d> > %s;\n" %(data_width, match_obj.group(3)))
                many_newline = 0
            else:
                f_hpp.write("\tsc_out<sc_bigint<%d> > %s;\n" %(data_width, match_obj.group(3)))
                many_newline = 0
        elif regx_reg_var.match(line):
            match_obj = regx_reg_var.match(line)
            data_width = int(match_obj.group(1))-int(match_obj.group(2))+1
            if data_width<=64:
                f_hpp.write("\tsc_signal<sc_int<%d> > %s;\n" %(data_width, match_obj.group(3)))
                many_newline = 0
            else:
                f_hpp.write("\tsc_signal<sc_bigint<%d> > %s;\n" %(data_width, match_obj.group(3)))
                many_newline = 0
        elif regx_assign.match(line):
            match_obj = regx_assign.match(line)
            match_obj1 = regx_assign.match(line)
            # rvar = re.sub("(?P<var>(?:\w+\[?\d*:?\d*\]?|\d*'[bdh][\da-f]+|\{|\}))", replace, match_obj.group(2))#等式右边变量
            rvar = re.sub("(?P<var>\w+\[?\d*:?\d*\]?|\d*'[bdh][\da-f]+|\{|\})", replace, match_obj.group(2))#每一个符合正则表达式的值会作为replace的输入参数
            sensitive_value = re.sub("(?P<var>\w+\[?\d*:?\d*\]?|\d*'[bdh][\da-f]+|\{|\}|\^|,|\+|&|\(|\)|\||\?|<|~|: )", replace1, match_obj1.group(2))
            # print(sensitive_value,"\t",match_obj1.group(2))
            sensitive_value = "".join(sensitive_value.split())
            sensitive_signal = re.split("<<", sensitive_value)
            sensitive_signal = list(sorted(set(sensitive_signal), key=sensitive_signal.index))
            del sensitive_signal[0]
            # print(sensitive_signal)
            sensitive_sta=[]
            sensitive_sta.append("\t\tsensitive ")
            for i in range(len(sensitive_signal)):
                sensitive_sta.append("< <%s"%sensitive_signal[i])
                if i==len(sensitive_signal)-1:
                    sensitive_sta.append(";\n")
            sensitive_sta=str("".join(sensitive_sta))
            pro_type_sta="\t\tSC_METHOD(assign%s);\n"%match_obj.group('lvar')
            ctor_sta=pro_type_sta+sensitive_sta
            ctor_text=ctor_text+ctor_sta
            f_hpp.write("\tvoid assign_%s();\n" %match_obj.group('lvar'));
            many_newline = 0
            f_cpp.write("void %s::assign_%s()\n{\n\t%s = %s;\n}\n\n" %(module_name, match_obj.group('lvar'), match_obj.group('lvar'), rvar))

        elif regx_always.match(line):
            match_obj=regx_always.match(line)
            always_nums=always_nums+1
            f_hpp.write("\n\tvoid always_block%d();"%always_nums)
            # f_cpp.write("void %s::always_block%d()\n"%(module_name,always_nums))
            always_block_array.append("void %s::always_block%d()\n"%(module_name,always_nums))
            print(always_block_array)
            always_text.append("\n\t\tSC_METHOD(always_block%s);\n"%always_nums)
            sensitive_always = ["\t\tsensitive"]
            if "posedge" in line:
                pos_val=re.findall("posedge (\w+)",line)
                pos_val="%s.pos()"%pos_val[0]
                sensitive_always.append("< <%s"%pos_val)

            if "negedge" in line:
                neg_val = re.findall("negedge (\w+)", line)
                neg_val = "%s.neg()" % neg_val[0]
                sensitive_always.append("< <%s"%neg_val)
            sensitive_always.append(";")
            sensitive_always = str("".join(sensitive_always))
            always_text.append(sensitive_always)

        # elif regx_always_replace.match(line):
        #     match_obj=regx_always_replace.match(line)
        #     print(1)
        # always_sensitive_text.append("%s"%sensitive_always)
    # elif regx_endmodule.match(line):
    #     f_hpp.write("};\n")



##获取always块
f_vlog.seek(0) ## 把句柄重新放回文件的开头
text=f_vlog.read()
# print(text)
text_always=re.findall(regx_always_replace,text)
text_always=text_always[0][0]
# print(text_always)
text_always=re.sub(regx_comment,"",text_always)

text_always1=re.sub("always@","#&always@",text_always)
text_always1=re.split("#&",text_always1)

for i in range(1,len(text_always1)):
    text_always2=text_always1[i]
    f_cpp.write(always_block_array[i-1])
    a = []
    ##对always块通用部分进行替换
    regx_begin = re.compile("begin.*")
    text_always2 = re.sub(regx_begin, "", text_always2)
    text_always2 = re.sub("end |end\n", "\tbreak;\n", text_always2)
    text_always2 = re.sub("<=", "=", text_always2)
    # text_always2=re.sub("\d*'b","",text_always2)
    text_always2 = re.sub("`", "", text_always2)
    regx_case = re.compile("'d(\d+)")
    text_always2 = re.sub(regx_case, "case\g<1>", text_always2)
    text_always2 = re.sub("\d*'b(\d+)", "\g<1>", text_always2)
    text_always2 = re.sub("endmodule", "", text_always2)
    text_always2 = re.sub(" *always.*", "", text_always2)
    text_always2 = re.sub("else", "\n\t}\nelse\n\t{", text_always2)
    # regx_range=re.compile("(\w+)\[(\d*):(\d*)\]")
    # text_always2=re.sub(regx_range,"\g<1>.range(\g<2>,\g<3>)",text_always2)
    # text_always2.split('\n')
    lines = text_always2.splitlines()
    # print(lines)

    ##按行读取always块并且转换
    many_newline = 0
    for line in lines:
        # print(line)
        if regx_value.match(line):
            match_obj2 = regx_value.match(line)
            rvar1 = re.sub("(?P<var>\w+\[?\d*:?\d*\]?|\d*'[bdh][\da-f]+)", replace2,
                           match_obj2.group(3))  # 每一个符合正则表达式的值会作为replace的输入参数
            lvar1 = re.sub("(?P<var>\w+\[?\d*:?\d*\]?|\d*'[bdh][\da-f]+)", replace3,
                           match_obj2.group(2))  # 每一个符合正则表达式的值会作为replace的输入参数
            a.append("\n%s%s = %s;" % (match_obj2.group(1), lvar1, rvar1))
            # print("\n\t%s = %s;\n" % (lvar1, rvar1),"+++")

        elif regx_value1.match(line):
            match_obj2 = regx_value1.match(line)
            rvar1 = re.sub("(?P<var>\w+\[?\d*:?\d*\]?|\d*'[bdh][\da-f]+)", replace2,
                           match_obj2.group(3))  # 每一个符合正则表达式的值会作为replace的输入参数
            lvar1 = re.sub("(?P<var>\w+\[?\d*:?\d*\]?|\d*'[bdh][\da-f]+)", replace3,
                           match_obj2.group(2))  # 每一个符合正则表达式的值会作为replace的输入参数
            a.append("\n%s%s = %s;" % (match_obj2.group(1), lvar1, rvar1))
            # a.append("\n\t%s = %s;\n" % (match_obj2.group('lvar'), rvar1))
            # print("\n\t\t%s = %s;\n" % (lvar1, rvar1), "+++")
        elif regx_ifsen.match(line):
            match_obj2 = regx_ifsen.match(line)
            line = match_obj2.group(1)
            if regx_if.match(line):
                match_obj2 = regx_if.match(line)
                line = re.sub(regx_if, "%s.read()==" % match_obj2.group(1), line)
                # print("\tif(%s)"%line, "___")
                a.append("\t\t\tif(%s)\n\t{\n" % line)
            elif regx_if1.match(line):
                match_obj2 = regx_if1.match(line)
                line = re.sub(regx_if1, "%s%s.read()" % (match_obj2.group(1), match_obj2.group(2)), line)
                # print("\tif(%s)" % line, "___")
                a.append("\t\t\tif(%s)\n\t{\n" % line)
        elif regx_case1.match(line):
            match_obj2 = regx_case1.match(line)
            a.append("%sswitch(%s.read() )\n\t{\n" % (match_obj2.group(1), match_obj2.group(2)))
            # print("\tswitch(%s.read() )"%match_obj2.group(1),"++++")
        else:

            a.append("\n")
            a.append(line)
            # print(line,"++++")
    a = "".join(a)
    a = re.sub("(\d+).read\(\)", "\g<1>", a)
    print(a)
    f_cpp.write("\n{\n\t%s\n\t}\n\t}\n" % a)

# regx_case=re.compile("'d(\d+)")
# text_always=re.sub(regx_case,"case\g<1>",text_always)
# regx_range=re.compile("(\w+)\[(\d*):(\d*)\]")
# text_always=re.sub(regx_range,"\g<1>.range(\g<2>,\g<3>)",text_always)
# r1=re.compile("(?<=\=) *(\w+)")
# text_always=re.sub(r1,"\g<1>.read()",text_always)
# r2=re.compile("(?<=\=)(.*\^ )(\w+)")
# # text_always=re.sub(r2,"\g<1>\g<2>.read()",text_always)



# print(text_always)
f_hpp.write("\tSC_CTOR(%s)\n\t{\n"%module_name)
f_hpp.write("%s"%ctor_text)
for i in range(len(always_text)):
    f_hpp.write("%s"%always_text[i])
f_hpp.write("\n\t}\n};")
f_vlog.close()

# if __name__ == "__main__":
#     def double(matched):
#         value = int(matched.group('value'))
#         return str(value * 2)
    
#     s = 'A23G4HFD567'
#     print(re.sub('(?P<value>\d+)', double, s))